 package com.gmrz.uaf.protocol.v1.json;
 
 import java.lang.reflect.Type;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.google.gson.InstanceCreator;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.gmrz.uaf.common.Constants;
import com.gmrz.uaf.common.TLVTag;
import com.gmrz.uaf.common.TLVType2;
import com.gmrz.uaf.protocol.v1.processor.exception.UAFErrorCode;
import com.gmrz.uaf.protocol.v1.schema.ASMSignResponse;
import com.gmrz.uaf.protocol.v1.schema.SignData;
import com.gmrz.util.Convert;
 
 public class ASMSignResponseAdapter
   implements InstanceCreator<ASMSignResponse>, JsonSerializer<ASMSignResponse>, JsonDeserializer<ASMSignResponse>
 {
   private static final Logger LOG = LogManager.getLogger(ASMSignResponseAdapter.class);
 
   public ASMSignResponse createInstance(Type type)
   {
     return new ASMSignResponse();
   }
 
   public JsonElement serialize(ASMSignResponse src, Type typeofSrc, JsonSerializationContext context)
   {
     try
     {
       byte[] signedData = src.getSignData().getReceivedBytes();
       TLVType2 signedDataTag = new TLVType2()
       {
       };
       signedDataTag.addTLVSegment(Constants.UAFV1AssertionTag.TAG_UAFV1_SIGNED_DATA.getTagValue(), signedData);
       byte[] signedDataTagBytes = signedDataTag.getTLVBytes();
 
       TLVType2 signatureTag = new TLVType2()
       {
       };
       signatureTag.addTLVSegment(Constants.UAFV1AssertionTag.TAG_SIGNATURE.getTagValue(), src.getSignature());
       byte[] signatureBytes = signatureTag.getTLVBytes();
 
       ByteBuffer buffer = ByteBuffer.allocate(signedDataTagBytes.length + signatureBytes.length).order(ByteOrder.LITTLE_ENDIAN);
 
       buffer.put(signedDataTagBytes).put(signatureBytes);
 
       TLVType2 responseTag = new TLVType2()
       {
       };
       responseTag.addTLVSegment(Constants.UAFV1AssertionTag.TAG_UAFV1_AUTH_ASSERTION.getTagValue(), buffer.array());
       String encoded = Convert.toBase64(responseTag.getTLVBytes());
       return context.serialize(encoded);
     } catch (Exception ex) {
       LOG.error("Error creating the Authentication TLV data, ", ex);
       throw new JsonParseException(UAFErrorCode.PROTOCOL_TLV_PARSING_FAILED.toString(), ex);
     }
   }
 
   public ASMSignResponse deserialize(JsonElement json, Type typeofT, JsonDeserializationContext context)
     throws JsonParseException
   {
     try
     {
       String encoded = json.getAsString();
 
       ByteBuffer buffer = ByteBuffer.wrap(Convert.fromBase64(encoded)).order(ByteOrder.LITTLE_ENDIAN);
 
       TLVTag responseTag = new TLVTag(TLVTag.readTag(buffer));//2字节标签
       byte[] responseBytes = responseTag.parseByteArray(buffer);
 
       ByteBuffer resBuffer = ByteBuffer.wrap(responseBytes).order(ByteOrder.LITTLE_ENDIAN);
 
       TLVTag signDataTag = new TLVTag(TLVTag.readTag(resBuffer));
       byte[] signedDataBytes = signDataTag.parseByteArray(resBuffer);
 
       TLVTag signatureTag = new TLVTag(TLVTag.readTag(resBuffer));
       byte[] signatureBytes = signatureTag.parseByteArray(resBuffer);
 
       ASMSignResponse retval = new ASMSignResponse();
       if ((signedDataBytes == null) || (signedDataBytes.length <= 0)) {
         throw new JsonParseException("Signed data not found in authentication response");
       }
       if ((signatureBytes == null) || (signatureBytes.length <= 0)) {
         throw new JsonParseException("Signature data not found in authentication response");
       }
 
       SignData signData = new SignData();
       signData.setReceivedBytes(signedDataBytes);
       signData.fromTLVBytes(signedDataBytes);
       retval.setSignedData(signData);
 
       retval.setSignature(signatureBytes);
 
       return retval;
     } catch (Exception ex) {
       LOG.error("Error parsing the Authentication TLV data, ", ex);
       throw new JsonParseException(UAFErrorCode.PROTOCOL_TLV_PARSING_FAILED.toString(), ex);
     }
   }
 }
